package cn.demomaster.quicklogger.config

import android.content.Context
import android.os.Build
import android.util.Log
import androidx.annotation.IntRange
import cn.demomaster.quicklogger.QdLog
import cn.demomaster.quicklogger.interceptor.LogInterceptor
import cn.demomaster.quicklogger.util.FileUtil
import java.io.File

class LogConfig(builder: LogConfigBuilder) {
    val showStackInfo: Boolean = builder._showStackInfo
    var TAG: String = builder._TAG
    var enable: Boolean = true // 是否启用
    var bufferMaxSize: Int = 10 * 1024 // 缓存阀值 当缓存大于此值清楚缓存
    var LOGFILE_SUFFIX: String = builder._LOGFILE_SUFFIX
    var lineHeaderFormat: String =builder._lineHeaderFormat
    var logLevel = builder._logLevel

    /**
     * 是否可以写日志
     * 用在 日志文件正在其他操作时，暂停写入。操作完成恢复写入
     */
    var canWriteAble: Boolean = true
    var usingGraphics: Boolean = true // 是否启用图形化 格式化输出
    var writerMode: Int = 1 // 写入模式 1 普通文件写入，0 mapbuffer写入
    var logFilePath: String // 存放日志文件的目录全路径
    var saveExternalStoragePath: String? = builder._saveExternalStoragePath // 存储在外部存储时的路径
    var saveInternalSoragePath: String? = builder._saveInternalSoragePath // 保存在内部存储缓存目录中的位置
    var saveExternalStorageAfterAndroidQ: Boolean =
        builder._saveExternalStorageAfterAndroidQ // 强制使用外置存储 针对Android Q以上的版本，但是需要 MANAGE_EXTERNAL_STORAGE。 true 保存在指定文件夹，false则保存在缓存目录
    var saveExternalStorageBeforeAndroidQ: Boolean =
        builder._saveExternalStorageBeforeAndroidQ // 强制使用外置存储 Android Q以下的版本。true 保存在指定文件夹，false则保存在缓存目录

    init { //File(builder._context.cacheDir, "logs").absolutePath
        val file: File = when {
            Build.VERSION.SDK_INT > Build.VERSION_CODES.Q -> {
                if (saveExternalStorageAfterAndroidQ) { // 强制使用外置存储 针对Android Q以上的版本，但是需要 MANAGE_EXTERNAL_STORAGE
                    File(saveExternalStoragePath)
                } else {
                    var diskCacheDir:String = FileUtil.getDiskCacheDir(builder._context)
                    File(diskCacheDir, saveInternalSoragePath)
                }
            }

            else -> {
                if (saveExternalStorageBeforeAndroidQ) { // 使用外置存储
                    File(saveExternalStoragePath)
                } else {
                    var diskCacheDir:String = FileUtil.getDiskCacheDir(builder._context)
                    File(diskCacheDir, saveInternalSoragePath)
                }
            }
        }

        println("SDK版本: ${Build.VERSION.SDK_INT}, 日志存储路径: ${file.absolutePath}")
        var DIR_PATH = file.absolutePath
        if (!DIR_PATH.trim().endsWith(File.separator)) {
            DIR_PATH += File.separator
        }
        logFilePath = DIR_PATH
    }
}

class LogConfigBuilder {
    var _showStackInfo: Boolean=true
    var _saveExternalStoragePath: String = "" // 外部路径
    var _saveInternalSoragePath: String = "/log/" // 保存在内部存储缓存目录中的位置
    var _TAG: String = QdLog.DEFAULT_TAG
    var _LOGFILE_SUFFIX: String = ".log"
    var _lineHeaderFormat: String =
        "time class:" // 正则表达式,处理头文件 level日志级别、 tag日志标签、 class所在类信息、 time打印时间 thread打印进程信息
    var _logLevel = Log.DEBUG
    //var _topLevelTag: String? = null
    //var _logCatLogLevel: Char? = null
    //var _fileLogLevel: Char? = null
//    var _showStackTraceInfo: Boolean = true
//    var _showFileTimeInfo: Boolean = true
//    var _showFilePidInfo: Boolean = true
//    var _showFileLogLevel: Boolean = true
//    var _showFileLogTag: Boolean = true
//    var _showFileStackTraceInfo: Boolean = true
    var _saveExternalStorageAfterAndroidQ: Boolean =
        false // 强制使用外置存储 针对Android Q以上的版本，但是需要 MANAGE_EXTERNAL_STORAGE。 true 保存在指定文件夹，false则保存在缓存目录
    var _saveExternalStorageBeforeAndroidQ: Boolean =
        true // 强制使用外置存储 Android Q以下的版本。true 保存在指定文件夹，false则保存在缓存目录
    var _deleteUnusedLogEntriesAfterDays: Int = 7
    var _context: Context
    var _interceptors: ArrayList<LogInterceptor>? = null

    constructor(context: Context) {
        this._context = context.applicationContext
    }
    fun addInterceptor(logInterceptor: LogInterceptor): LogConfigBuilder {
        if(_interceptors == null){
            _interceptors = ArrayList()
        }
        _interceptors!!.add(logInterceptor)
        return this
    }
    fun build(): LogConfig {
        requireNotNull(_context) { "Context must not be null" }
        return LogConfig(this)
    }

    fun setShowStackInfo(showStackInfo: Boolean): LogConfigBuilder {
        this._showStackInfo = showStackInfo
        return this
    }
    fun setLogLevel(logLevel: Int): LogConfigBuilder {
        this._logLevel = logLevel
        return this
    }
    fun setSaveInternalSoragePath(saveInternalSoragePath: String): LogConfigBuilder {
        this._saveInternalSoragePath = saveInternalSoragePath
        return this
    }

    fun setSaveExternalStoragePath(saveExternalStorageDirFile: File): LogConfigBuilder {
        this._saveExternalStoragePath = saveExternalStorageDirFile.absolutePath
        return this
    }

    fun setSaveExternalStorageAfterAndroidQ(saveExternalStorageAfterAndroidQ: Boolean): LogConfigBuilder {
        this._saveExternalStorageAfterAndroidQ = saveExternalStorageAfterAndroidQ
        return this
    }

    fun setSaveExternalStorageBeforeAndroidQ(saveExternalStorageBeforeAndroidQ: Boolean): LogConfigBuilder {
        this._saveExternalStorageBeforeAndroidQ = saveExternalStorageBeforeAndroidQ
        return this
    }

    /**
     * 删除过了几天无用日志条目
     */
    fun deleteUnusedLogEntriesAfterDays(
        @IntRange(
            from = 1,
            to = Int.MAX_VALUE.toLong()
        ) days: Int
    ): LogConfigBuilder {
        this._deleteUnusedLogEntriesAfterDays = days
        return this
    }

    fun setLineHeaderFormat(lineHeaderFormat: String): LogConfigBuilder {
        this._lineHeaderFormat = lineHeaderFormat
        return this
    }
}